﻿using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace GBricks.Collections
{
  [Serializable]
  public class ItemReadOnlyKeyedCollection<TKey, TItem> : ReadOnlyKeyedCollection<TKey, TItem>
  {
    private static readonly ItemReadOnlyKeyedCollection<TKey, TItem> EmptyInstance = new ItemReadOnlyKeyedCollection<TKey, TItem>(new EmptyItemKeyedCollection());

    public ItemReadOnlyKeyedCollection(ItemKeyedCollection<TKey, TItem> list)
      : base(list) {
      Argument.NotNull(list, "list");
    }

    public static new ItemReadOnlyKeyedCollection<TKey, TItem> Empty {
      [DebuggerStepThrough]
      get {
        Contract.Ensures(Contract.Result<ItemReadOnlyKeyedCollection<TKey, TItem>>() != null);
        return EmptyInstance;
      }
    }

    protected new ItemKeyedCollection<TKey, TItem> Items {
      [DebuggerStepThrough]
      get {
        Contract.Ensures(Contract.Result<ItemKeyedCollection<TKey, TItem>>() != null);
        return (ItemKeyedCollection<TKey, TItem>)base.Items;
      }
    }

    [ContractInvariantMethod]
    private void Invariant() {
      Contract.Invariant(Items != null);
    }

    [Pure]
    public bool TryGetItem(TKey key, out TItem item) {
      return Items.TryGetItem(key, out item);
    }

    [Pure]
    public TItem GetItemOrDefault(TKey key, TItem @default = default(TItem)) {
      Argument.NotNull(key, "key");
      return Items.GetItemOrDefault(key, @default);
    }

    [Serializable]
    private sealed class EmptyItemKeyedCollection : ItemKeyedCollection<TKey, TItem>
    {
      protected override TKey GetKeyForItem(TItem item) {
        Throw.InvalidOperation();
        return default(TKey);
      }
    }
  }
}
